package com.jxpanda.spring.module.wechat.component.http.base;

import com.jxpanda.infrastructure.core.tollkit.GenericTypeKit;
import com.jxpanda.infrastructure.core.tollkit.ReflectionKit;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpMethod;

import java.util.function.Function;

/**
 * 微信接口url
 *
 * @author Panda
 */
@RequiredArgsConstructor
@SuppressWarnings("AlibabaAbstractClassShouldStartWithAbstractNaming")
public abstract class WechatApi<Q, B, R> {

    private Class<Q> queryType;

    private Class<B> bodyType;

    private Class<R> returnType;

    /**
     * 接口方法，默认是GET
     */
    public HttpMethod getMethod() {
        return HttpMethod.GET;
    }

    /**
     * 接口地址
     *
     * @return url
     */
    public abstract String getUrl();

    public Class<Q> getQueryType() {
        if (queryType == null) {
            queryType = getGenericType(this.getClass(), 0);
        }
        return queryType;
    }

    public Class<B> getBodyType() {
        if (bodyType == null) {
            bodyType = getGenericType(this.getClass(), 1);
        }
        return bodyType;
    }

    public Class<R> getReturnType() {
        if (returnType == null) {
            returnType = getGenericType(this.getClass(), 2);
        }
        return returnType;
    }

    public static <X> Class<X> getGenericType(Class<?> clazz, int index) {
        return GenericTypeKit.getSuperClassGenericType(clazz, WechatApi.class, index);
    }

    public Builder<WechatApi<Q, B, R>> builder() {
        return new Builder<>(this);
    }

    public class Builder<API extends WechatApi<Q, B, R>> {
        private Q query;
        private B body;
        private final API wechatApi;

        private Builder(API wechatApi) {
            this.wechatApi = wechatApi;
        }

        public Builder<API> query(Q query) {
            this.query = query;
            return this;
        }

        public Builder<API> query(Function<Q, Q> queryHandler) {
            if (this.query != null) {
                this.query = queryHandler.apply(this.query);
            }
            return this;
        }

        public Builder<API> body(B body) {
            this.body = body;
            return this;
        }

        public Builder<API> body(Function<B, B> bodyHandler) {
            if (this.body != null) {
                this.body = bodyHandler.apply(this.body);
            }
            return this;
        }

        public WechatHttpRequest<R> build() {
            return new WechatHttpRequest<>(wechatApi, query, body);
        }

    }


}
